<template>
  <v-overlay
      :value="showDialog"
      :style="{backdropFilter: `${showDialog ? 'blur(50px)' : 'unset'}`}"
      :z-index="202">
    <v-dialog
        class="rounded-xl"
        v-model="showDialog"
        width="75vw"
        max-width="900"
        hide-overlay
        @click:outside="handleDialogClose">
      <v-app style="width: 900px; height: 580px; overflow: hidden">
        <v-snackbar
            v-model="showAlert"
            :color="alertBgColor"
            rounded="lg"
            top app absolute
            max-width="unset"
            min-height="unset"
            :timeout="2000">
          {{ alertContent }}
        </v-snackbar>
        <div class="login-popup-container">
          <div class="right-content">
            <v-window
                v-model="currentForm">
              <v-window-item :value="0">
                <div class="login-form">
                  <div class="change-form font-weight-medium">
                    <span>没有账号？</span>
                    <span
                        class="change-btn blue--text lighten-1"
                        data-current="login"
                        @click="handleChangeForm">立即注册</span>
                  </div>
                  <div class="form-title font-weight-bold">账户登录</div>
                  <div class="form">
                    <v-form ref="loginForm">
                      <v-container>
                        <v-row>
                          <v-text-field
                              label="账号"
                              v-model="loginFormValue.account"
                              :rules="[rules.accountRequired, rules.account]"
                              :error="accountOrPasswordError"
                              hint="电子邮箱或手机号"
                              autocomplete/>
                        </v-row>
                        <v-row>
                          <v-text-field
                              label="密码"
                              v-model="loginFormValue.password"
                              type="password"
                              :rules="[rules.pwdRequired]"
                              :error="accountOrPasswordError"
                              autocomplete/>
                        </v-row>
                        <v-row
                            class="captcha-row__default"
                            :class="showLoginCaptchaRow ? 'captcha-row__show' : 'captcha-row__hide'">
                          <v-text-field
                              label="验证码"
                              v-model="loginFormValue.captcha"
                              maxlength="4"
                              :rules="[rules.loginCaptcha]"
                              :hint="loginCaptchaHint"
                              :persistent-hint="loginCaptchaError || !loginCaptchaLoaded"
                              :disabled="loginCaptchaError || !loginCaptchaLoaded"/>
                          <v-img
                              height="40"
                              width="120"
                              contain
                              :src="loginCaptchaUrl"
                              @loadstart="handleLoginCaptchaLoadStart"
                              @load="handleLoginCaptchaLoad"
                              @error="handleLoginCaptchaError"
                              @click="handleRefreshCaptchaClick">
                            <v-row
                                class="fill-height ma-0 grey lighten-4 rounded-lg"
                                v-show="!loginCaptchaLoaded"
                                align="center"
                                justify="center"
                                @click="">
                              <v-progress-circular
                                  v-show="!loginCaptchaLoaded && !loginCaptchaError"
                                  :indeterminate="!loginCaptchaLoaded && !loginCaptchaError"
                                  width="2"
                                  size="20"
                                  color="primary"/>
                              <v-hover
                                  v-slot="{ hover }"
                                  v-show="loginCaptchaError">
                                <v-icon
                                    :class="{ 'on-hover': hover }"
                                    @click.stop="handleRefreshCaptchaClick(true)">
                                  fas fa-repeat
                                </v-icon>
                              </v-hover>
                            </v-row>
                          </v-img>
                        </v-row>
                        <v-row
                            class="auto-and-forget mb-6 button-transfer__default"
                            :class="showLoginCaptchaRow ? '' : 'button-transfer__unmoved'">
                          <v-checkbox
                              label="下次自动登录"
                          ></v-checkbox>
                          <v-btn class="forgot-pwd" depressed small plain text>
                            忘记密码
                          </v-btn>
                        </v-row>
                        <v-row
                            class="button-transfer__default"
                            :class="showLoginCaptchaRow ? '' : 'button-transfer__unmoved'">
                          <v-btn
                              depressed
                              block
                              color="primary"
                              :loading="loginBtnLoading"
                              @click="handleLoginBtnClick">
                            登录
                          </v-btn>
                        </v-row>
                      </v-container>
                    </v-form>
                  </div>
                </div>
              </v-window-item>
              <v-window-item :value="1">
                <div class="register-form">
                  <div class="change-form font-weight-medium">
                    <span>已有账号？</span>
                    <span
                        class="change-btn blue--text lighten-1"
                        data-current="register"
                        @click="handleChangeForm">立即登录</span>
                  </div>
                  <div class="form-title font-weight-bold">
                    新用户注册
                  </div>
                  <div class="form">
                    <v-form ref="registerForm">
                      <v-container>
                        <v-row>
                          <v-text-field
                              label="手机号"
                              v-model="registerFormValue.phone"
                              :rules="[rules.phone]"/>
                        </v-row>
                        <v-row class="captcha-row">
                          <v-text-field
                              label="验证码"
                              v-model="registerFormValue.captcha"
                              :rules="[rules.registerCaptcha]"
                              validate-on-blur
                              hint="短信验证码"/>
                          <v-btn
                              :loading="registerCaptchaSending || !allowSendRegisterCaptcha"
                              depressed
                              :disabled="typeof rules.phone(registerFormValue.phone) !== 'boolean' || !allowSendRegisterCaptcha"
                              color="primary"
                              @click="sendRegisterCaptcha">
                            发送验证码
                            <template v-slot:loader>
                              <v-progress-circular
                                  v-show="registerCaptchaSending"
                                  :indeterminate="registerCaptchaSending"
                                  width="2"
                                  size="20"
                                  color="primary"/>
                              <span v-show="!registerCaptchaSending">
                          {{ registerCaptchaResendTimeLeft }}s后重新发送
                        </span>
                            </template>
                          </v-btn>
                        </v-row>
                        <v-row
                            class="password-row__default"
                            :class="showRegisterPwdRow ? 'password-row__show' : 'password-row__hide'">
                          <v-text-field
                              label="密码"
                              v-model="registerFormValue.password"
                              :rules="[rules.registerPwd]"/>
                        </v-row>
                        <v-row
                            class="user-agreement mb-6 button-transfer__default"
                            :class="showRegisterPwdRow ? '' : 'button-transfer__unmoved'">
                          <v-checkbox
                              label="我已阅读并同意用户协议"
                              :rules="[rules.required]"/>
                        </v-row>
                        <v-row
                            class="button-transfer__default"
                            :class="showRegisterPwdRow ? '' : 'button-transfer__unmoved'">
                          <v-btn
                              depressed
                              block
                              color="primary"
                              @click="handleRegisterBtnClick">
                            注册
                          </v-btn>
                        </v-row>
                      </v-container>
                    </v-form>
                  </div>
                </div>
              </v-window-item>
              <v-window-item :value="2">
                <div class="username-form">
                  <div class="change-form font-weight-medium">
                  <span
                      class="change-btn blue--text lighten-1"
                      data-current="username"
                      @click="currentForm = 1">
                    返回上一步
                  </span>
                  </div>
                  <div class="form-title font-weight-bold">
                    设置用户名
                  </div>
                  <div class="form">
                    <v-form ref="usernameForm">
                      <v-container>
                        <v-row>
                          <v-text-field
                              label="用户名"
                              v-model="registerFormValue.username"
                              :rules="[rules.registerUsername]"
                              hint="请输入新的用户名"/>
                        </v-row>
                        <v-row class="complete-btn">
                          <v-btn
                              depressed
                              block
                              color="primary"
                              :loading="registerBtnLoading"
                              @click="handleRegisterBtnClick">
                            完成注册
                          </v-btn>
                        </v-row>
                      </v-container>
                    </v-form>
                  </div>
                </div>
              </v-window-item>
            </v-window>
          </div>
          <div class="left-content"></div>
        </div>
      </v-app>
    </v-dialog>
  </v-overlay>
</template>

<script>
import {getLoginCaptcha, getPhoneCaptcha, login, register} from "../../api";
import myAxios from "../../api/myAxios";

/**
 * @description 登录弹出窗组件
 * @property {Boolean} value 控制登录弹出窗的关闭开启
 * @property {Number} defaultForm 默认显示的表单，0:登录，1:注册，默认为0
 * @event loginSuccess 登陆成功回调事件
 * @event registerSuccess 注册成功回调事件
 * @event close 弹出窗关闭回调事件
 * @example <loginPopup v-model="true" :defaultForm="1" @loginSuccess="..."/>
 */
export default {
  name: "loginPopup",
  props: {
    value: {
      type: Boolean,
      default: false
    },
    defaultForm: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      showDialog: false, //同步props中的value属性，用于控制窗体关闭开启
      showAlert: false, //是否显示消息提示框
      alertContent: '', //消息提示框的文字内容
      alertBgColor: '', //消息提示框背景颜色
      currentForm: 0, //当前显示的表单，0:登录，1:注册
      loginFormValue: {
        account: '13119806343',
        password: '123456',
        captcha: ''
      }, //登陆表单中用户输入的数据
      registerFormValue: {
        phone: '',
        password: '',
        captcha: '',
        username: '',
      }, //注册表单中用户输入的数据
      showLoginCaptchaRow: false, //是否显示登陆表单中的验证码输入行
      showRegisterPwdRow: false, //是否显示注册表单中的密码输入行
      loginCaptchaUrl: '', //登陆表单验证码图片url
      loginCaptchaLoaded: false, //登陆表单验证码是否已经加载完成
      loginCaptchaError: false, //登陆表单验证码是否加载失败
      loginBtnLoading: false, //登陆按钮是否处于加载状态
      registerBtnLoading: false, //注册按钮是否处于加载状态
      allowSendRegisterCaptcha: true, //是否允许发送注册表单手机验证码
      registerCaptchaSending: false, //注册表单手机验证码发送中
      registerCaptchaResendTimer: null, //注册表单手机验证码发送计时器
      registerCaptchaResendTimeLeft: 60, //注册表单手机验证码重发倒计时（秒）
      rules: {
        required: value => !!value,
        accountRequired: value => !!value || '请正确填写电子邮箱或手机号',
        pwdRequired: value => !!value || '请填写密码',
        account: value => {
          const email = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
          const phone = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/;
          return email.test(value) || phone.test(value) || '请填写正确的电子邮箱或手机号';
        },
        loginCaptcha: value => /^[a-zA-Z0-9]{4}$/.test(value) || !this.showLoginCaptchaRow || '请正确填写验证码',
        phone: value => /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/.test(value) || '请填写正确的手机号',
        registerCaptcha: value => /^[0-9]{6}$/.test(value) || '请正确填写验证码',
        registerPwd: value => /^[a-zA-Z0-9]{6,18}$/.test(value) || !this.showRegisterPwdRow || '请输入6-18位英文/数字',
        registerUsername: value => !!value || '请填写用户名'
      }, //表单验证规则
      accountOrPasswordError: false, //登陆时账号或密码错误
    }
  },
  methods: {
    // 初始化/还原表单
    init() {
      switch (this.currentForm) {
        case  0:
          this.$refs.loginForm.reset();
          break;
        case 1:
          this.$refs.registerForm.reset();
          break;
        case 2:
          this.$refs.usernameForm.reset();
          this.currentForm = 1;
          break;
      }
      this.showLoginCaptchaRow = false;
      this.showRegisterPwdRow = false;
      this.loginCaptchaUrl = '';
    },
    // 切换登录/注册表单
    handleChangeForm(e) {
      this.utils.throttle(() => {
        this.init();
        this.currentForm = e.currentTarget.dataset.current === 'login' ? 1 : 0;
      }, 1000);
    },
    // 登录按钮点击事件
    handleLoginBtnClick() {
      this.utils.throttle(async () => {
        this.accountOrPasswordError = false;
        if (!this.showLoginCaptchaRow) {
          if (this.$refs.loginForm.validate()) {
            this.loginBtnLoading = true;
            this.refreshLoginCaptcha();
            setTimeout(() => {
              this.showLoginCaptchaRow = true;
              this.loginBtnLoading = false;
            }, 300);
          }
        } else {
          if (this.$refs.loginForm.validate()) {
            this.loginBtnLoading = true;
            myAxios.post('/api/ucenter/member/login', {
              mobile: this.loginFormValue.account,
              password: this.loginFormValue.password,
              code: this.loginFormValue.captcha
            }).then(res => {
              switch (res.code) {
                case 0:
                  //登陆成功
                  this.$emit('loginSuccess');
                  this.alert('登陆成功', 'success');
                  this.showDialog = false;
                  this.$forceUpdate()
                  this.init();
                  this.$message({
                    message: '登陆成功',
                    type: 'success'
                  });
                  break;
                case 1000005:
                  //验证码错误
                  this.loginFormValue.captcha = '';
                  this.alert('您输入的验证码有误', 'error');
                  this.refreshLoginCaptcha();
                  break;
                case 1000007:
                  //密码错误
                  this.accountOrPasswordError = true;
                  this.loginFormValue.captcha = '';
                  this.alert('您输入的密码有误', 'error');
                  this.refreshLoginCaptcha();
                  break;
                default:
                  this.accountOrPasswordError = true;
                  this.loginFormValue.captcha = '';
                  this.alert(res.message, 'error');
                  this.refreshLoginCaptcha();
                  break;
              }
            }).catch(err => {
              this.alert('登录失败', 'error');
            });
            this.loginBtnLoading = false;
          } else {
            this.showAlert = true;
          }
        }
      }, 1000);
    },
    // 注册按钮点击事件
    handleRegisterBtnClick() {
      this.utils.throttle(async () => {
        if (!this.showRegisterPwdRow) {
          if (this.$refs.registerForm.validate()) {
            this.registerBtnLoading = true;
            setTimeout(() => {
              this.showRegisterPwdRow = true;
              this.registerBtnLoading = false;
            }, 300);
          }
        } else {
          if (this.$refs.registerForm.validate()) {
            if (this.currentForm === 1) {
              this.currentForm = 2;
            } else {
              if (this.$refs.usernameForm.validate()) {
                this.registerBtnLoading = true;
                await register(this.registerFormValue.phone, this.registerFormValue.password, this.registerFormValue.captcha, this.registerFormValue.username).then(res => {
                  switch (res.code) {
                    case 0:
                      this.$emit('registerSuccess');
                      this.alert('注册成功', 'success');
                      this.showDialog = false;
                      this.currentForm = 0;
                      this.init();
                      break;
                    default:
                      this.currentForm = 1;
                      this.alert(res.message, 'error');
                      break;
                  }
                }).catch(err => {
                  this.alert('注册失败', 'error');
                });
                this.registerBtnLoading = false;
              }
            }
          }
        }
      }, 1000);
    },
    // 登陆表单验证码开始加载监听事件
    handleLoginCaptchaLoadStart() {
      this.loginCaptchaError = false;
      this.loginCaptchaLoaded = false;
    },
    // 登陆表单验证码加载完毕监听事件
    handleLoginCaptchaLoad() {
      this.loginCaptchaLoaded = true;
    },
    // 登陆表单验证码加载失败监听事件
    handleLoginCaptchaError() {
      this.loginCaptchaError = true;
    },
    handleRefreshCaptchaClick(isError = false) {
      this.utils.throttle(() => {
        this.refreshLoginCaptcha(isError);
      }, 300);
    },
    // 刷新登陆表单验证码
    refreshLoginCaptcha(isError) {
      if (!isError) {
        this.loginCaptchaUrl = this.getLoginCaptcha(Math.random());
      } else {
        this.loginCaptchaLoaded = false;
        this.loginCaptchaError = false;
        setTimeout(() => {
          this.loginCaptchaUrl = this.getLoginCaptcha(Math.random());
        }, 1000);
      }
    },
    // 发送注册表单手机验证码
    sendRegisterCaptcha() {
      this.utils.throttle(async () => {
        this.allowSendRegisterCaptcha = false;
        this.registerCaptchaSending = true;
        const res = await getPhoneCaptcha(this.registerFormValue.phone);
        switch (res.code) {
          case 20000:
            //发送短信验证码成功
            this.alert('已发送短信验证码', 'success');
            this.registerCaptchaSending = false;
            this.registerCaptchaResendTimer = setInterval(() => {
              if (this.registerCaptchaResendTimeLeft > 0) {
                this.registerCaptchaResendTimeLeft -= 1;
              } else {
                clearInterval(this.registerCaptchaResendTimer);
                this.registerCaptchaResendTimer = null;
                this.allowSendRegisterCaptcha = true;
                this.registerCaptchaResendTimeLeft = 60;
              }
            }, 1000);
            break;
          default:
            //发送失败
            this.alert(res.message, 'error');
            this.registerCaptchaSending = false;
            this.allowSendRegisterCaptcha = true;
            break;
        }
      }, 1000);
    },
    // 登录弹出窗关闭事件
    handleDialogClose() {
      this.init();
      this.showDialog = false;
      this.$emit('close');
    },
    /**
     * 显示消息提示
     * @param {String} text 消息提示框的文字内容
     * @param {String} type 消息提示框的类型，支持success/warning/error
     */
    alert(text, type) {
      this.alertContent = text;
      this.alertBgColor = type === 'success' ? '#4caf50' : type === 'warning' ? '#fb8c00' : type === 'error' ? '#ff5252' : '';
      this.showAlert = true;
    },
    getLoginCaptcha(random) {
      return getLoginCaptcha(random)
    }
  },
  computed: {
    // 登录验证码提示语
    loginCaptchaHint() {
      if (!this.loginCaptchaLoaded) {
        return this.loginCaptchaError ? '验证码加载失败，请重试' : '正在加载验证码，请稍后';
      } else {
        return '请输入图形验证码';
      }
    },
    // 映射props中的value，强制在值变化时触发监听器
    isShowDialog() {
      return this.value;
    },
    // 映射props中的defaultForm，强制在值变化时触发监听器
    displayFormIndex() {
      return this.defaultForm;
    }
  },
  watch: {
    // 监听props中的value的变化，同步到data中的showDialog
    isShowDialog(nval) {
      this.showDialog = nval;
    },
    // 监听props中的defaultForm的变化，同步到data中的currentForm
    displayFormIndex(nval) {
      this.currentForm = nval;
    }
  },
  mounted() {
    this.currentForm = this.defaultForm;
  }
}
</script>

<style lang="scss" scoped>
@import "loginPopup";
</style>